package testCase

import (
	"context"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
	"goproject/commonType"
	"goproject/mongodb/testMicroservice"
	ctrl "sigs.k8s.io/controller-runtime"
	"sync"
)

var log = ctrl.Log.WithName("mongodb/testCase")
var mutex sync.Mutex

type Store struct {
	collection *mongo.Collection
}

func NewStore(db *mongo.Database) *Store {
	return &Store{
		collection: db.Collection("testCase"),
	}
}

// Create 测试用例
func (s *Store) Create(ctx context.Context, testCase commonType.TestCase) (commonType.TestCase, error) {
	if testCase.ID == nil {
		newID := primitive.NewObjectID()
		testCase.ID = &newID
	}
	result, err := s.collection.InsertOne(ctx, testCase)
	if err != nil {
		log.Error(err, "create testCase failed", "testCase", testCase)
		return commonType.TestCase{}, err
	}
	objectID := result.InsertedID.(primitive.ObjectID)
	testCase.ID = &objectID
	return testCase, nil
}

// Get 获取测试用例
func (s *Store) Get(ctx context.Context, id primitive.ObjectID) (commonType.TestCase, error) {
	var testCase commonType.TestCase
	err := s.collection.FindOne(ctx, primitive.M{"_id": id}).Decode(&testCase)
	if err != nil {
		log.Error(err, "get testCase error", "id", id)
		return commonType.TestCase{}, err
	}
	return testCase, nil
}

// GetListByTestMicroserviceId  根据testMicroservice_id获取测试用例列表
func (s *Store) GetListByTestMicroserviceId(ctx context.Context, testMicroserviceId primitive.ObjectID, skip int, pageSize int) ([]commonType.TestCase, error) {
	var testCase []commonType.TestCase
	findOptions := options.Find()
	findOptions.SetSkip(int64(skip))
	findOptions.SetLimit(int64(pageSize))
	cursor, err := s.collection.Find(context.TODO(), primitive.M{"testMicroservice_id": testMicroserviceId}, findOptions)
	if err != nil {
		log.Error(err, "get testCase list error", "testMicroservice_id", testMicroserviceId)
		return nil, err
	}
	err = cursor.All(ctx, &testCase)
	if err != nil {
		log.Error(err, "get testCase list error", "testMicroservice_id", testMicroserviceId)
		return nil, err
	}
	return testCase, nil
}

func (s *Store) Update(ctx context.Context, testCase commonType.TestCase) (commonType.TestCase, error) {
	mutex.Lock()
	defer mutex.Unlock()
	update := bson.M{
		"$set": bson.M{
			"testMicroservice_id": testCase.TestMicroserviceID,
			"selectedReq":         testCase.SelectedReq,
			"selectedFault":       testCase.SelectedFault,
			"dependency":          testCase.Dependency,
			"status":              testCase.Status,
			"response":            testCase.Response,
		},
	}

	_, err := s.collection.UpdateOne(ctx, bson.M{"_id": testCase.ID}, update)
	if err != nil {
		log.Error(err, "update testCase error", "id", testCase.ID)
		return commonType.TestCase{}, err
	}
	return testCase, nil
}

// 根据record_id获取测试用例列表
func (s *Store) GetListByRecordId(ctx context.Context, recordId primitive.ObjectID) ([]commonType.TestCase, error) {
	// 根据record_id获取所有测试微服务
	testMicroservices, err := testMicroservice.NewStore(s.collection.Database()).GetAllByRecordId(ctx, recordId)
	if err != nil {
		log.Error(err, "get testMicroservice list error", "record_id", recordId)
		return nil, err
	}
	// 根据各个测试微服务id查询所有的测试用例
	var testCaseList []commonType.TestCase
	for _, testMicroservice := range testMicroservices {
		testCases, err := s.GetListByTestMicroserviceId(ctx, *testMicroservice.ID, 0, 0)
		if err != nil {
			log.Error(err, "get testCase list error", "testMicroservice_id", testMicroservice.ID)
			return nil, err
		}
		testCaseList = append(testCaseList, testCases...)
	}
	return testCaseList, nil
}

// 获取所有测试用例
func (s *Store) GetAll(ctx context.Context) ([]commonType.TestCase, error) {
	var testCaseList []commonType.TestCase
	cursor, err := s.collection.Find(ctx, primitive.M{})
	if err != nil {
		log.Error(err, "get testCase list error")
		return nil, err
	}
	err = cursor.All(ctx, &testCaseList)
	if err != nil {
		log.Error(err, "get testCase list error")
		return nil, err
	}
	return testCaseList, nil
}
